package com.xtxk.utils.util;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.io.Charsets;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.http.MediaType;

import com.alibaba.fastjson.JSONObject;
import com.xtxk.common.constant.QuantityConstant;

/**
 * @author tiger
 * httpsUtils 请求公共类
 */
public class HttpsUtil {
	
	static Logger log = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);
	
	/**
	 * 绕过SSL验证
	 * 
	 * @throws NoSuchAlgorithmException
	 * @throws KeyManagementException
	 */
	public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
		SSLContext sslContext = SSLContext.getInstance("SSLv3");
		// 实现一个X509TrustManager接口，用于绕过验证，不用修改里面的方法
		X509TrustManager trustManager = new X509TrustManager() {
			@Override
			public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
					String paramString) throws CertificateException {
			}

			@Override
			public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
					String paramString) throws CertificateException {
			}

			@Override
			public java.security.cert.X509Certificate[] getAcceptedIssuers() {
				return null;
			}
		};

		sslContext.init(null, new TrustManager[] { trustManager }, null);
		return sslContext;
	}

	/**
	 * 绕过SSL证书，发送Get请求
	 * 
	 * @param url
	 * @param params
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws KeyManagementException
	 * @throws NoSuchAlgorithmException
	 */
	public static String doGet(String url, Map<String, Object> params) {
		String result = null;
		try {
			// 采用绕过验证的方式处理https请求
			SSLContext sslContext = createIgnoreVerifySSL();
			// 设置协议http和https对应的处理socket链接工厂的对象
			final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,
					NoopHostnameVerifier.INSTANCE);
			final Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
					.register("http", new PlainConnectionSocketFactory()).register("https", sslsf).build();

			final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
			cm.setMaxTotal(100);

			// 创建自定义的httpclient对象
			CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).setConnectionManager(cm).build();
			url=paramHandle(url, params);
			log.info("请求地址：URL:{}",url);
			// 创建get方式请求对象
			HttpGet httpGet = new HttpGet(url);
			// 执行请求操作，并拿到结果（同步阻塞）
			CloseableHttpResponse response = httpClient.execute(httpGet);
			if (response.getStatusLine().getStatusCode() == 200) {
				// 获取结果实体
				HttpEntity httpEntity = response.getEntity();
				// 按指定编码转换结果实体为String类型
				return EntityUtils.toString(httpEntity, "UTF-8");
			}
			// 释放链接
			response.close();
		} catch (IOException e) {
			result = e.getMessage();
		} catch (KeyManagementException e) {
			result = e.getMessage();
		} catch (NoSuchAlgorithmException e) {
			result = e.getMessage();
		}
		return result;
	}

	public static String paramHandle(String url, Map<String, Object> params) {
		// 装填参数
		StringBuffer param = new StringBuffer();
		if (params != null && !params.isEmpty()) {
			int i = 0;
			for (String key : params.keySet()) {
				if (i == 0) {
					param.append("?");
				} else {
					param.append("&");
				}
				param.append(key).append("=").append(params.get(key));
				i++;
			}
			url += param;
		}
		return url;
	}

	public static String doPost(String url, Map<String, Object> params)
			throws IOException, KeyManagementException, NoSuchAlgorithmException {
		return doPost(url, params, MediaType.APPLICATION_JSON_UTF8_VALUE);
	}

	/**
	 * 绕过SSL证书，发送Post请求
	 * 支持"application/x-www-form-urlencoded","application/json;charset=UTF-8"
	 * 
	 * @param url
	 * @param param
	 * @throws IOException
	 * @throws KeyManagementException
	 * @throws NoSuchAlgorithmException
	 */
	public static String doPost(String url, Map<String, Object> params, String mediaType)
			throws IOException, KeyManagementException, NoSuchAlgorithmException {
		// 采用绕过验证的方式处理https请求
		SSLContext sslContext = createIgnoreVerifySSL();
		final SSLConnectionSocketFactory sslsf;

		// 设置协议http和https对应的处理socket链接工厂的对象
		sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
		final Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
				.register("http", new PlainConnectionSocketFactory()).register("https", sslsf).build();

		final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
		cm.setMaxTotal(100);

		// 创建自定义的httpclient对象
		CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).setConnectionManager(cm)
				.build();

		String result = null;
		// 创建post方式请求对象
		HttpPost httpPost = new HttpPost(url);

		List<NameValuePair> nvps = new ArrayList<NameValuePair>();

		if (params != null) {
			Set<String> keySet = params.keySet();
			for (String key : keySet) {
				nvps.add(new BasicNameValuePair(key, params.get(key) + ""));
			}
		}

		if (StringUtils.equals(mediaType, MediaType.APPLICATION_FORM_URLENCODED_VALUE)) {
			httpPost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
		} else if (StringUtils.equals(mediaType, MediaType.APPLICATION_JSON_UTF8_VALUE)) {
			httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
			httpPost.setEntity(new StringEntity(JSONObject.toJSONString(params), StandardCharsets.UTF_8));
		}
		log.info("POST请求地址：URL:{}",url);
		log.info("POST请求参数：params:{}",params);
		// 执行请求操作，并拿到结果（同步阻塞）
		CloseableHttpResponse response = httpClient.execute(httpPost);
		if (response.getStatusLine().getStatusCode() == 200) {
			// 获取结果实体
			HttpEntity httpEntity = response.getEntity();
			// 按指定编码转换结果实体为String类型
			result = EntityUtils.toString(httpEntity, "UTF-8");
		}

		// 释放链接
		response.close();
		return result;
	}
	
	/**
	 * 绕过SSL证书，发送Post请求
	 * 支持"application/x-www-form-urlencoded","application/json;charset=UTF-8"
	 * 
	 * @param url
	 * @param param
	 * @throws IOException
	 * @throws KeyManagementException
	 * @throws NoSuchAlgorithmException
	 */
	public static String doPost(String url, String params, String mediaType)
			throws IOException, KeyManagementException, NoSuchAlgorithmException {
		// 采用绕过验证的方式处理https请求
		SSLContext sslContext = createIgnoreVerifySSL();
		final SSLConnectionSocketFactory sslsf;

		// 设置协议http和https对应的处理socket链接工厂的对象
		sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
		final Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
				.register("http", new PlainConnectionSocketFactory()).register("https", sslsf).build();

		final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
		cm.setMaxTotal(100);

		// 创建自定义的httpclient对象
		CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).setConnectionManager(cm)
				.build();

		String result = null;
		// 创建post方式请求对象
		HttpPost httpPost = new HttpPost(url);
		if(StringUtils.isNotBlank(params)) {
			StringEntity s = new StringEntity(params,Charsets.UTF_8);
			s.setContentEncoding("UTF-8");
			s.setContentType("application/x-www-form-urlencoded");
			httpPost.setEntity(s);
		}
		// 执行请求操作，并拿到结果（同步阻塞）
		CloseableHttpResponse response = httpClient.execute(httpPost);
		if (response.getStatusLine().getStatusCode() == 200) {
			// 获取结果实体
			HttpEntity httpEntity = response.getEntity();
			// 按指定编码转换结果实体为String类型
			result = EntityUtils.toString(httpEntity, "UTF-8");
		}

		// 释放链接
		response.close();
		return result;
	}
	/**
	 * 发送body为xml格式
	 * @param url
	 * @param params
	 * @return
	 * @throws IOException
	 * @throws KeyManagementException
	 * @throws NoSuchAlgorithmException
	 */
	public static String doPost(String url, String params)
			throws IOException, KeyManagementException, NoSuchAlgorithmException {
		return doPost(url, params, MediaType.APPLICATION_ATOM_XML_VALUE);
	}

	
	/**
	 * 解析获取的Data数据
	 * @param st
	 */
	public static Object getData(String st) {
		return st==null ? null : JSONObject.parseObject(st).get(QuantityConstant.DATA);
	}
}
